/*
	The MIT License

	Copyright (c) 2010 IFMO/GameDev Studio

	Permission is hereby granted, free of charge, to any person obtaining a copy
	of this software and associated documentation files (the "Software"), to deal
	in the Software without restriction, including without limitation the rights
	to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
	copies of the Software, and to permit persons to whom the Software is
	furnished to do so, subject to the following conditions:

	The above copyright notice and this permission notice shall be included in
	all copies or substantial portions of the Software.

	THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
	IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
	FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
	AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
	LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
	OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
	THE SOFTWARE.
*/
// fmod_sys.h - 


#pragma once

class EFMODSoundSystem;
class EFMODSoundBuffer;
class EFMODSound3D;
class EFMODSoundTrack;
class EFMODSoundGeometry;
class EFMODSoundReverb;

typedef HardRef<EFMODSoundSystem>		EPxFMODSoundSystem;
typedef HardRef<EFMODSoundBuffer>		EPxFMODSoundBuffer;
typedef HardRef<EFMODSound3D>			EPxFMODSound3D;
typedef HardRef<EFMODSoundTrack>		EPxFMODSoundTrack;
typedef HardRef<EFMODSoundGeometry>	EPxFMODSoundGeometry;
typedef HardRef<EFMODSoundReverb>		EPxFMODSoundReverb;



class EFMODSoundReverb : public ISoundReverb {
	public:
		
								EFMODSoundReverb		( FMOD::Reverb *reverb, const EPoint& pos, float min_distance, float max_distance, FMOD_REVERB_PROPERTIES* properties, soundReverbType_t type );
		virtual					~EFMODSoundReverb		( void );
		virtual	void			Set3DProperties			( const EPoint& pos, float min_distance, float max_distance );
		virtual	EPoint			GetPosition				( void );
		virtual void			GetDistance				( float &min_distance, float &max_distance );

				void			SetReverbProperties		( FMOD_REVERB_PROPERTIES* properties );

	protected:
		FMOD::Reverb *reverb;
		soundReverbType_t type;
};



class EFMODSoundGeometry : public ISoundGeometry {
	public:

								EFMODSoundGeometry		( FMOD::Geometry *geometry ) { this->geometry = geometry; };
		virtual					~EFMODSoundGeometry		( void ) { geometry->release(); };
		virtual	void			SetPosition				( const EPoint &pos );
		virtual void			SetOrient				( const EQuaternion &orient );

	protected:
		FMOD::Geometry	*geometry;
		EPoint pos;
		EQuaternion orient;
};


class EFMODSoundBuffer : public ICoreObject {	
	public:
								EFMODSoundBuffer		( FMOD::System *system, const char *path, bool sound3D);
								~EFMODSoundBuffer		( void );
				FMOD::Sound		*GetFMODSound			( void );
				uint			GetLength				( void );
				const char		*Name					( void ) const { return name.c_str(); }
				void			CreateSound				( void );
				void			CreateNullSound			( void );
				bool			Is3DSound				( void );

	protected:

		string name;
		FMOD::System		*fmod_sys;
		FMOD::Sound			*fmod_sound;

		bool				sound3d;
};


class EFMODSound3D : public ISound3D {
	public:
							EFMODSound3D		( EFMODSoundSystem *ss_system, EFMODSoundBuffer *buffer );
		virtual				~EFMODSound3D		( void );

		virtual void		Play				( bool loop );
		virtual void		Stop				( void );
		virtual void		Pause				( void );
		virtual void		Unpause				( void );
		virtual bool		IsPlaying			( void ) const;
		
		virtual void		SetPose				( const EPoint &position, const EQuaternion &orient );
		virtual void		GetPose				( EPoint &position, EQuaternion &orient ) const;
		virtual void		SetVelocity			( const EVector &linear_velocity );
		virtual void		GetVelocity			( EVector &linear_velocity ) const;
		
		virtual void		SetVolume			( float volume );
		virtual void		SetPitch			( float pitch );
		virtual void		SetMute				( bool mute );		
		virtual	void		SetSpread			( float angle );
		virtual	void		SetDoplerLevel		( float level );
		virtual	void		SetMinMaxDistance	( float min, float max );

	protected:
	
		bool				CheckChannel		( void ) const;

		EFMODSoundSystem		*ss_system;
		EFMODSoundBuffer		*buffer;
		mutable FMOD::Channel	*fmod_channel;

		EVector		velocity;
		EPoint		position;
		EQuaternion	orient;
		
		bool	mute;

		float	volume;
		float	pitch;

		float	spread;
		float	dopler_level;
		float	min_distance;
		float	max_distance;

};


class EFMODSoundTrack : public ISoundTrack {
	public:
								EFMODSoundTrack		( EFMODSoundSystem *ss_system, FMOD::Sound *fmod_sound );
		virtual					~EFMODSoundTrack	( void );
		virtual	void			Play				( void );
		virtual void			Pause				( void );
		virtual void			Stop				( void );
		virtual void			SetVolume			( float volume );
		virtual float			GetLength			( void );
		virtual void			SetPos				( float time );
		virtual float			GetPos				( void );
		virtual void			SetMute				( bool mute );

	protected:

		EFMODSoundSystem	*ss_system;

		FMOD::Sound			*fmod_sound;
		FMOD::Channel		*fmod_channel;
	};


class EFMODSoundSystem : public ISoundSystem {
	public:
											EFMODSoundSystem		( void );
		virtual								~EFMODSoundSystem		( void );
		virtual void						FreeSounds				( void ); 
		virtual void						Play2DSound				( const char *path, float volume, float panning );
		virtual void						SetListener				( const EPoint &pos, const EVector &view, const EVector &up, const EVector &vel );
		virtual IPxSound3D					CreateSoundSource		( const char *path );
		virtual void						DestroySoundSource		( ISound3D *sound );
		virtual IPxSoundTrack				CreateSoundTrack		( const char *path );
		virtual void						DestroySoundTrack		( ISoundTrack *track );
		virtual IPxSoundGeometry			CreateSoundGeometry		( const IPxTriMesh input_mesh, const EPoint &pos, const EQuaternion &orient  );
		virtual IPxSoundReverb				CreateReverb			( const EPoint& pos, float min_distance, float max_distance, soundReverbType_t type );
		virtual void						Frame					( void );
		virtual	void						RenderDebug				( void );		
		virtual void						SetMute					( bool mute );

				FMOD_REVERB_PROPERTIES		GetReverbProperties		( soundReverbType_t type );

				FMOD::Channel				*CreateChannel			( FMOD::Sound *sound );
				EPxFMODSoundBuffer			RegisterSoundBuffer		( const char *path, bool sound3d );
					
	protected:

		
		IPxVar	fmod_prof;
		
		vector <EPxFMODSoundBuffer>	sound2d_file_list;
		vector <EPxFMODSoundBuffer>	sound3d_file_list;
		vector <IPxSound3D>			sound3d_list;	
		vector <IPxSoundTrack>		sound_track_list;	
		vector <IPxSoundGeometry>	sound_geometry_list;	
		vector <IPxSoundReverb>		sound_reverb_list;	

		FMOD::System	*fmod_sys;
	

	public:
		IPxVar			fmod_show_stats;	/*	"0"		*/
		IPxVar			sound_spread;
		IPxVar			sound_dopler_level;
		IPxVar			sound_min_distance;
		IPxVar			sound_max_distance;

	protected:
		FMOD::ChannelGroup	*sound3d_channels;

	};
